
`include "common_header.verilog"

//  *************************************************************************
//  File : gen_pat_10g.v
//  *************************************************************************
//  This program is controlled by a written license agreement.
//  Unauthorized Reproduction or Use is Expressly Prohibited. 
//  Copyright (c) 2001-2002-2003-2004 Morethanip
//  MorethanIP GmbH, An der Steinernen Brueke 1, 85757 Karlsfeld, Germany
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: gen_pat_10g.v,v 1.1 2012/10/29 10:06:07 dk Exp $
//  Author : Serge S.
//  Initial: 01/04/2002
//  *************************************************************************
//  Description: 10G Base-R PCS Transmit: Test Pattern Generator
//  *************************************************************************

module gen_pat_10g (

   reset,
   sw_reset,
   clk,
   clk_ena,
   en_gen_pat,
   sel_pat,
   seed_1,
   seed_2,
   data_in_type,
   data_in,
   seed_ld,
   seed_out,
   data_out_type,
   data_out);
   
input   reset;                  //  asynch reset
input   sw_reset;               //  Software Synchronous Reset
input   clk;                    //  system clock     
input   clk_ena;                //  system clock enable (66-bit block valid)   
input   en_gen_pat;             //  Enable Test pattern generator 
input   sel_pat;                //  Select pattern : 1 => 00 / 0 => Local Fault 
input   [57:0] seed_1;          //  Seed 1
input   [57:0] seed_2;          //  Seed 2
input   [1:0]  data_in_type;    //  Data Block Type from encoder
input   [63:0] data_in;         //  Data Block from encoder
output  seed_ld;                //  load seed 
output  [57:0] seed_out;        //  Seed out      
output  [1:0]  data_out_type;   //  Data Block type (10: data / 01: control)
output  [63:0] data_out;        //  Data out to Scrambler 

reg     seed_ld; 
reg     [57:0] seed_out; 
wire    [1:0]  data_out_type; 
wire    [63:0] data_out; 

wire    en_gen_pat_s;           //  Enable Test pattern generator 
reg     sel_pat_s;              //  Select pattern : 0 => 00 / 1 => Local Fault 
reg     [57:0] seed_1_s;        //  Seed 1
wire    [57:0] seed_1_s_n;      //  Seed 1 invert
reg     [57:0] seed_2_s;        //  Seed 2    
wire    [57:0] seed_2_s_n;      //  Seed 2 invert   
reg     [1:0] sel_seed;         //  Select Seed to use       
reg     sel_seed_0;             //  Select Seed to use delayed       
reg     [57:0] mux_seed;        //  Seed mux
wire    [63:0] mux_pat;         //  Pattern mux
reg     [63:0] mux_pat_inv;     //  Pattern inverted
reg     inv_pat;                //  Invert Selected pattern
reg     [6:0] cnt_block;        //  128 block counter
reg     [1:0] cnt_seq;          //  Sequence counter  
reg     seed_ld_s;              //  load seed
wire    [1:0] pat_out_type; 
reg     [63:0] pat_out; 

// sync async inputs
// ------------
mtip_xsync #(1) U_SYENPAT (
          .data_in(en_gen_pat),
          .reset(reset),
          .clk(clk),
          .data_s(en_gen_pat_s));

// Wire pattern generator or direct encoder pass-through
// -----------------------------------------------------

assign pat_out_type  = 2'b 01;  // always control words (10: data / 01: control)

assign data_out_type = en_gen_pat_s==1'b 1 ? pat_out_type : data_in_type;
assign data_out      = en_gen_pat_s==1'b 1 ? pat_out      : data_in;

//  Pattern mux
// ------------
   
assign mux_pat = sel_pat_s == 1'b 0 ?   64'b 0000000100000000000000000000000000000001000000000000000001010101 : //  2 Local Fault
                                        64'b 0000000000000000000000000000000000000000000000000000000000000000;  //  00
   

//  Muxes  
//  -----

always @(posedge clk or posedge reset)
   begin : p_mux
   if (reset == 1'b 1)
      begin
      sel_pat_s <= 1'b 0;               //  Select pattern : 0 => 00 / 1 => Local Fault 
      seed_1_s <= {58{1'b 0}};          //  Seed 1
      seed_2_s <= {58{1'b 0}};          //  Seed 2    
      mux_seed <= {58{1'b 0}};          //  Seed mux
      mux_pat_inv <= {64{1'b 0}};       //  Pattern inverted
      pat_out <= {64{1'b 0}};          //  Data out
      seed_out <= {58{1'b 0}};          //  Seed out
      end
   else
      begin

      //  Seed Sample
      // ------------
   
      seed_1_s     <= seed_1;           //  Seed 1
      seed_2_s     <= seed_2;           //  Seed 2   
      sel_pat_s    <= sel_pat;          //  Select pattern : 0 => 00 / 1 => Local Fault
  
      if (clk_ena==1'b 1)
         begin

      //  Seed mux
      // ---------
   
         case (sel_seed)
         2'b 00:
            begin
            mux_seed <= seed_1_s;   
            end
         2'b 01:
            begin
            mux_seed <= seed_1_s_n;   
            end
         2'b 10:
            begin
            mux_seed <= seed_2_s;   
            end
         2'b 11:
            begin
            mux_seed <= seed_2_s_n;   
            end
         default:
            begin
            mux_seed <= seed_1_s;   
            end
         endcase
         seed_out <= mux_seed; 
         
      //  Pattern inverted
      // -----------------
      
         if (inv_pat == 1'b 1)
            begin
            mux_pat_inv <= ~mux_pat;   
            end
         else
            begin
            mux_pat_inv <= mux_pat;   
            end
   
      //  Data out
      // ---------
      
         if (en_gen_pat_s == 1'b 1)
            begin
            pat_out <= mux_pat_inv;   
            end
         else
            begin
            pat_out <= {64{1'b 0}};   
            end
   
         end // ck_ena
      end
   end

//  Seed 1 invert
// --------------

assign seed_1_s_n = ~seed_1_s; 

//  Seed 2   invert
// ----------------

assign seed_2_s_n = ~seed_2_s; 

//  Mux Control 
//  -----------

always @(posedge clk or posedge reset)
   begin : p_control
   if (reset == 1'b 1)
      begin
      cnt_block <= {7{1'b 0}};  //  128 block counter
      cnt_seq <= {2{1'b 0}};    //  Sequence counter  
      sel_seed <= {2{1'b 0}};   //  Select Seed to use  
      sel_seed_0 <= 1'b 0;      //  Select Seed to use delayed    
      inv_pat <= 1'b 0;         //  Invert Selected pattern
      seed_ld_s <= 1'b 0;       //  load seed
      seed_ld <= 1'b 0;         //  load seed
      end
   else
      begin
      if (sw_reset==1'b 1 | en_gen_pat_s==1'b 0)
         begin
         cnt_block <= {7{1'b 0}};  
         cnt_seq <= {2{1'b 0}};  
         sel_seed <= {2{1'b 0}};   
         sel_seed_0 <= 1'b 0;     
         inv_pat <= 1'b 0; 
         seed_ld_s <= 1'b 0; 
         seed_ld <= 1'b 0; 
         end
      else if (clk_ena==1'b 1)
         begin
   
      //  128 block counter
      // ------------------
      
            cnt_block <= cnt_block + 7'b 0000001;   
   
      //  Sequence counter 
      // -----------------
      
         if (cnt_block == 7'b 1111111)
            begin
            cnt_seq <= cnt_seq + 2'b 01;   
            end
   
      //  Select Seed to use -- Invert Selected pattern
      // ----------------------------------------------
         case (cnt_seq)
         2'b 00:
            begin
            sel_seed <= 2'b 00;   
            inv_pat <= 1'b 0;   
            end
         2'b 01:
            begin
            sel_seed <= 2'b 01;   
            inv_pat <= 1'b 1;   
            end
         2'b 10:
            begin
            sel_seed <= 2'b 10;   
            inv_pat <= 1'b 0;   
            end
         2'b 11:
            begin
            sel_seed <= 2'b 11;   
            inv_pat <= 1'b 1;   
            end
         default:
            begin
            sel_seed <= 2'b 00;   
            inv_pat <= 1'b 0;   
            end
         endcase
         sel_seed_0 <= sel_seed[0];   // Select Seed to use delayed 
   
         //  load seed
         // ----------
         
         if ((sel_seed[0] == 1'b 1 & sel_seed_0 == 1'b 0 | 
              sel_seed[0] == 1'b 0 & sel_seed_0 == 1'b 1) & en_gen_pat_s == 1'b 1)
            begin
            seed_ld_s <= 1'b 1;   
            end
         else
            begin
            seed_ld_s <= 1'b 0;   
            end
         seed_ld <= seed_ld_s;   //  load seed
         end
      end
   end

endmodule // module gen_pat